package com.zhuliwei.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhuliwei.constants.SystemConstants;
import com.zhuliwei.domain.ResponseResult;
import com.zhuliwei.domain.entity.LoginUser;
import com.zhuliwei.domain.entity.User;
import com.zhuliwei.domain.entity.WechatUserEntity;
import com.zhuliwei.domain.vo.BlogUserLoginVo;
import com.zhuliwei.domain.vo.UserInfoVo;
import com.zhuliwei.domain.vo.WxLoginVo;
import com.zhuliwei.service.UserService;
import com.zhuliwei.utils.*;
import com.zhuliwei.wxlogin.WechatTrustManager;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Objects;

/**
 * 微信登录
 *
 * @author 朱力维
 * @time 2024/7/30 16:30
 **/
@RestController
@RequestMapping("/wx")
public class WxLoginController {
    @Resource
    private RedisCache redisCache;
    @Autowired
    UserService iUserService;
    private final static Logger log = LoggerFactory.getLogger(WechatUtils.class);
    private final static String appid = "wx9b8084a340cfd264"; //凭证
    private final static String appsecret = "bffaa4dce81a8b6c1a3bdd461723b8d3"; //凭证密钥
    //userinfo
    public final static String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?openid=OPENID&lang=zh_CN";


    @GetMapping("/getToken/{code}")
    public ResponseResult getToken(@PathVariable String code) throws IOException {
        String s = "appid=" + appid +
                "&secret=" + appsecret +
                "&code=" + code +
                "&grant_type=authorization_code";
        // 发送HTTP POST请求
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=wx9b8084a340cfd264&secret=bffaa4dce81a8b6c1a3bdd461723b8d3&grant_type=authorization_code&js_code=" + code;


        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        //默认值我GET
        con.setRequestMethod("GET");

        //添加请求头
//        con.setRequestProperty("User-Agent", USER_AGENT);

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'GET' request to URL : " + url);
        System.out.println("Response Code : " + responseCode);
        System.out.println("Response Message :" + con.getResponseMessage());
        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        String result = response.toString();
//        JSONObject jsonObject = new JSONObject();
//        JSONObject jsonObject1 = jsonObject.getJSONObject(result);
        System.out.println("result = " + result);
        String token = result.substring(result.indexOf("{\"session_key\":\"") + 16, result.indexOf("\",\""));
//        String token = jsonObject1.getString("session_key");
        System.out.println("token = " + token);
        int startIndex = result.indexOf("\"openid\":\"") + "\"openid\":\"".length();
        int endIndex = result.indexOf("\"", startIndex);
        String openid = result.substring(startIndex, endIndex);
//        String openid = jsonObject1.getString("openid");
        System.out.println("openid = " + openid);
        WxLoginVo loginVo = new WxLoginVo();
        loginVo.setToken(token);
        loginVo.setOpenId(openid);
        return ResponseResult.okResult(loginVo);
    }


    @GetMapping("/login")
    public ResponseResult login(String accessToken, String openid, HttpServletRequest request) {
//        System.out.println("code = " + code);
//        // 获取接口访问凭证
//        String accessToken = getToken(code).getAccessToken();
//        String openid = getToken(code).getOpenid();
        System.out.println("accessToken = " + accessToken);
        System.out.println("openid = " + openid);
        /**
         * 获取用户信息
         */
//        WechatUserEntity wechatUserEntity = getUserInfo(accessToken,openid);
//        System.out.println("wechatUserEntity："+ wechatUserEntity.toString());
//        if (wechatUserEntity == null) {
//            return ResponseResult.errorResult(500, "获取用户信息失败,请检查accessToken或openid是否有效");
//        }
//        System.out.println("关注时间：" + wechatUserEntity.getSubscribeTime());
//        System.out.println("昵称：" + wechatUserEntity.getNickName());
//        System.out.println("性别：" + wechatUserEntity.getSex());
//        System.out.println("国家：" + wechatUserEntity.getCountry());
//        System.out.println("省份：" + wechatUserEntity.getProvince());
//        System.out.println("城市：" + wechatUserEntity.getCity());
//        System.out.println("语言：" + wechatUserEntity.getLanguage());
//        System.out.println("头像：" + wechatUserEntity.getAvatarUrl());
//        String nickname = wechatUserEntity.getNickName();
        User user = new User();
        if (Objects.isNull(iUserService.findByOpenId(openid))) {
            //将用户信息存在数据库中
            user.setOpenId(openid);
            user.setNickName("微信用户");
            user.setAvatar("https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0");
            LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
            lqw.eq(User::getUserName, user.getNickName());
            user.setUserName(SystemConstants.WX_USER_PREFIX + new Date().getTime());
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            user.setPassword(bCryptPasswordEncoder.encode("123456"));
            // 添加到数据库
            iUserService.save(user);
        } else {
            user = iUserService.findByOpenId(openid);
        }
        LoginUser loginUser = new LoginUser(user, null);
        // 无需认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, null);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //        // 认证
//        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//        // 判断认证是否通过
//        if (Objects.isNull(authenticate)) {
//            throw new RuntimeException("用户名或密码错误");
//        }
        //获取userid 生成token
//        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();//获取用户实体
        String userId = user.getId();
        String jwt = JwtUtil.createJWT(userId);
        //把用户信息存入redis
        redisCache.setCacheObject(SystemConstants.BLOG_LOGIN_PREFIX + userId, loginUser);
        //把token和userinfo封装 返回
        //把User封装成UserInfoVo
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class);
        // 记录登录后的IP地址
        String ipAddress = IPUtil.getIpAddress(request);
        user.setIpaddress(ipAddress);
        // 记录登录时间
        user.setLogintime(new Date());
        iUserService.updateById(user);
        BlogUserLoginVo blogUserLoginVo = new BlogUserLoginVo(jwt, userInfoVo);
        return ResponseResult.okResult(blogUserLoginVo);
//        return ResponseResult.okResult(user);
    }

    /**
     * 获取用户信息
     *
     * @param accessToken 接口访问凭证
     * @return WeixinUserInfo
     */
    public static WechatUserEntity getUserInfo(String accessToken, String openId) {

        WechatUserEntity wechatUserEntity = null;
        // 拼接请求地址
        String requestUrl = userInfoUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
        // 获取用户信息
        JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
        System.out.println("JsonObject：" + jsonObject.toString());
        if (null != jsonObject) {
            try {
                wechatUserEntity = new WechatUserEntity();
                // 用户的标识
                wechatUserEntity.setOpenId(jsonObject.getString("openid"));
                wechatUserEntity.setUnionId(jsonObject.getString("unionid"));
                // 关注状态（1是关注，0是未关注），未关注时获取不到其余信息
//                wechatUserEntity.setSubscribe(jsonObject.getInt("subscribe"));
                // 用户关注时间
//                wechatUserEntity.setSubscribeTime(jsonObject.getString("subscribe_time"));
                // 昵称
                wechatUserEntity.setNickName(jsonObject.getString("nickname"));
//                 用户的性别（1是男性，2是女性，0是未知）
//                wechatUserEntity.setSex(jsonObject.getInt("sex"));
//                 用户所在国家
//                wechatUserEntity.setCountry(jsonObject.getString("country"));
//                 用户所在省份
//                wechatUserEntity.setProvince(jsonObject.getString("province"));
//                 用户所在城市
//                wechatUserEntity.setCity(jsonObject.getString("city"));
                // 用户的语言，简体中文为zh_CN
//                wechatUserEntity.setLanguage(jsonObject.getString("language"));
                // 用户头像
                wechatUserEntity.setAvatarUrl(jsonObject.getString("headimgurl"));
            } catch (Exception e) {
                int errorCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                System.err.printf("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);
                return null;
            }
        }
        return wechatUserEntity;
    }

    /**
     * 发送https请求
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式（GET、POST）
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new WechatTrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes(StandardCharsets.UTF_8));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuilder stringBuilder = new StringBuilder();
            while ((str = bufferedReader.readLine()) != null) {
                stringBuilder.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.parseObject(stringBuilder.toString());
        } catch (ConnectException ce) {
            System.err.printf("连接超时：{}", ce);
        } catch (Exception e) {
            System.err.printf("https请求异常：{}", e);
        }
        return jsonObject;
    }
}

